package com.fita.entity.order.reverse;

import com.demo2do.core.entity.exception.BusinessException;
import com.fita.entity.agent.Agent;
import com.fita.entity.agent.AgentCompany;
import com.fita.entity.order.OrderPayType;
import com.fita.entity.order.PayStatus;
import com.fita.entity.order.reverse.aviation.AviationBook;
import com.fita.entity.order.reverse.aviation.AviationRequest;
import com.fita.entity.order.reverse.cruises.CruisesBook;
import com.fita.entity.order.reverse.cruises.CruisesRequest;
import com.fita.entity.order.reverse.hotel.HotelBook;
import com.fita.entity.order.reverse.hotel.HotelRequest;
import com.fita.entity.order.reverse.journey.JourneyBook;
import com.fita.entity.order.reverse.journey.JourneyRequest;
import com.fita.entity.principal.Principal;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @description: 反向订单
 * @author: 11200
 * @date: 2019/8/21
 */
@Entity
@Table(name = "reverse_order")
@DynamicUpdate
public class ReverseOrder {


    @Id
    @GeneratedValue
    private Long id;

    /**
     *
     */
    private String code;

    private Date createTime;

    @Enumerated(EnumType.STRING)
    private ReverseOrderStatus status;

    /**
     * 类型
     */
    @Enumerated(EnumType.STRING)
    private ReverseOrderType type;

    @Enumerated(EnumType.STRING)
    private PayStatus payStatus;

    @ManyToOne
    private Agent agent;

    /**
     * 售价
     */
    private BigDecimal price;

    /**
     * 成本价
     */
    private BigDecimal costPrice;

    /**
     * 实际支付价格
     */
    private BigDecimal actualPayPrice;

    /**
     * 最后一次支付时间
     */
    private Date payTime;

    private String payCode;

    @Enumerated(EnumType.STRING)
    private OrderPayType payType;

    private HotelRequest hotelRequest;

    private HotelBook hotelBook;

    private CruisesRequest cruisesRequest;

    private CruisesBook cruisesBook;

    private JourneyRequest journeyRequest;

    private JourneyBook journeyBook;

    private AviationBook aviationBook;

    private AviationRequest aviationRequest;

    @ManyToOne
    private Enquiry enquiry;

    @Column(name = "is_disabled")
    private boolean disabled;

    @ManyToOne
    private Principal operator;

    /**
     * 订单备注（客户不可见）
     */
    private String orderRemark;

    /**
     * 标记支付操作人
     */
    @ManyToOne
    private Principal markPayOperator;

    /**
     * 出票订单号
     */
    private String ticketOrderCode;

    /**
     * 出票时间
     */
    private Date ticketTime;

    /**
     * 退款金额
     */
    private BigDecimal refundPrice;

    /**
     * 核销时间
     */
    private Date consumedTime;

    /**
     * 退款流水号
     */
    private String refundCode;

    /**
     * 客户姓名
     */
    private String customName;

    /**
     * 客户英文姓
     */
    private String customEnglishPrefix;

    /**
     * 客户英文名
     */
    private String customEnglishName;

    /**
     * 客户电话
     */
    private String customMobile;

    /**
     * 邮箱
     */
    private String customEmail;

    /**
     * 一级代理公司
     */
    @ManyToOne
    private AgentCompany primaryAgentCompany;

    /**
     * 最晚支付时间
     */
    private Date lastPayTime;

    /**
     * 支付凭据
     */
    private String payPic;

    /**
     * 取消时间
     */
    private Date cancelTime;

    /**
     * 标记支付标志
     */
    @Column(name = "is_mark_pay")
    private boolean markPay;

    /**
     * 线上支付标志
     */
    @Column(name = "is_online_pay")
    private boolean onlinePay;

    /**
     * 标题
     */
    private String title;

    /**
     * sku头图
     */
    private String skuPic;

    /**
     * sku
     */
    @ManyToOne
    private Sku sku;

    /**
     *
     */
    public ReverseOrder() {
    }

    /**
     * 直接创建订单
     *
     * @param type
     * @param principal
     */
    public ReverseOrder(ReverseOrderType type, Principal principal) {
        this.code = "RO" + new Date().getTime();
        this.createTime = new Date();
        this.type = type;
        this.status = ReverseOrderStatus.EDITING;
        this.operator = principal;
        this.payStatus = PayStatus.UNPAID;
        this.markPay = false;
        this.onlinePay = false;
        this.title = type.getDescription();
    }

    /**
     * 从询价单创建订单
     *
     * @param enquiry
     * @param principal
     */
    public ReverseOrder(Enquiry enquiry, Principal principal) {

        this.code = "RO" + new Date().getTime();
        this.enquiry = enquiry;
        this.customName = enquiry.getCustomerName();
        this.customMobile = enquiry.getCustomerMobile();
        this.createTime = new Date();
        this.type = enquiry.getType();
        this.agent = enquiry.getAgent();
        this.status = ReverseOrderStatus.EDITING;
        this.operator = principal;
        this.payStatus = PayStatus.UNPAID;
        this.markPay = false;
        this.onlinePay = false;

        this.title = enquiry.getSku().getTitle();
        this.skuPic = enquiry.getSku().getPic();
        this.sku = enquiry.getSku();
    }

    /**
     * 可以标记支付吗
     * @return
     */
    public boolean canMarkPay(){
        return !onlinePay;
    }

    /**
     * 可以线上支付吗
     * @return
     */
    public boolean canOnlinePay(){
        return !markPay;
    }

    /**
     * 修改价格
     *
     * @param price
     * @param costPrice
     * @param lastPayTime
     * @return
     */
    public ReverseOrder editPrice(BigDecimal price, BigDecimal costPrice, Date lastPayTime) {

        this.price = price;
        this.costPrice = costPrice;
        this.lastPayTime = lastPayTime;

        return this;
    }

    /**
     * 发送到客户
     *
     * @param agent
     * @return
     */
    public ReverseOrder sendToClient(Agent agent) {

        this.status = ReverseOrderStatus.UNPAID;
        this.agent = agent;

        return this;
    }

    /**
     * 支付
     *
     * @param amount
     * @param payDate
     * @return
     */
    public ReverseOrder pay(BigDecimal amount, Date payDate) {

        this.payTime = payDate;

        if (this.actualPayPrice == null){
            this.actualPayPrice = new BigDecimal(0);
        }
        this.actualPayPrice = actualPayPrice.add(amount);

        if (isNeedPay()){
            this.payStatus = PayStatus.PART_PAY;
            this.status = ReverseOrderStatus.UNPAID;
        }
        if (!isNeedPay()){
            this.payStatus = PayStatus.PAID;
            this.status = ReverseOrderStatus.WAITING_FOR_TICKET;
        }
        this.onlinePay = true;

        return this;
    }

    /**
     * @return
     */
    public BigDecimal getPrettyPrice() {
        if (this.price != null) {
            return this.price.divide(new BigDecimal(100));
        }
        return BigDecimal.ZERO;
    }

    /**
     * @return
     */
    public BigDecimal getPrettyActualPayPrice() {
        if (this.actualPayPrice != null) {
            return this.actualPayPrice.divide(new BigDecimal(100));
        }
        return BigDecimal.ZERO;
    }

    /**
     * 获取格式化退款价格
     *
     * @return
     */
    public BigDecimal getPrettyRefundPrice() {
        if (this.refundPrice != null) {
            return this.refundPrice.divide(new BigDecimal(100));
        }
        return BigDecimal.ZERO;
    }

    /**
     * @return
     */
    public BigDecimal getPrettyCostPrice() {
        if (this.costPrice != null) {
            return this.costPrice.divide(new BigDecimal(100));
        }
        return BigDecimal.ZERO;
    }

    /**
     * 标记支付
     *
     * @return
     * @param price
     * @param payTime
     */
    public ReverseOrder markPay(BigDecimal price, Date payTime) {

        this.markPay = true;

        this.payTime = payTime;

        if (this.actualPayPrice == null){
            this.actualPayPrice = new BigDecimal(0);
        }
        this.actualPayPrice = this.actualPayPrice.add(price);

        //部分支付
        if (isNeedPay()){
            this.payStatus = PayStatus.PART_PAY;
            this.status = ReverseOrderStatus.UNPAID;
        }
        if (!isNeedPay()){
            this.status = ReverseOrderStatus.WAITING_FOR_TICKET;
            this.payStatus = PayStatus.PAID;
        }
        return this;
    }


    /**
     * 取消订单
     *
     * @param refundPrice
     * @return
     */
    public ReverseOrder cancel(BigDecimal refundPrice) {

        // 待退款取消失败
        if (this.status.isWaitingForRefund() || this.status.isCanceled() || this.status.isConsumed()) {
            throw new BusinessException("订单状态异常");
        }

        if (hasActualPayPrice()) {
            this.status = ReverseOrderStatus.WAITING_FOR_REFUND;
            this.refundPrice = refundPrice;
        } else {
            this.status = ReverseOrderStatus.CANCELED;
        }
        this.cancelTime = new Date();

        return this;
    }

    /**
     * @return
     */
    public ReverseOrder delete() {

        if (this.status.isEditing() || this.status.isConsumed() || this.status.isCanceled()) {
            this.disabled = true;
            return this;
        } else {
            throw new BusinessException("当前状态不能删除");
        }

    }

    /**
     * 标记出票
     *
     * @param orderCode
     * @param ticketTime
     * @return
     */
    public ReverseOrder markTicket(String orderCode, Date ticketTime) {

        this.ticketOrderCode = orderCode;
        this.ticketTime = ticketTime;
        this.status = ReverseOrderStatus.TICKETED;

        return this;
    }

    /**
     * 标记核销
     *
     * @param orderId
     * @return
     */
    public ReverseOrder markConsumed(Long orderId) {

        if (this.status.isTicketed()) {

            this.status = ReverseOrderStatus.CONSUMED;
            this.consumedTime = new Date();

            return this;
        } else {
            throw new BusinessException("只能在已出票状态下标记核销");
        }
    }


    /**
     * 标记退款
     *
     * @param refundCode
     * @return
     */
    public ReverseOrder markRefund(String refundCode) {

        if (this.status.isWaitingForRefund() && this.payStatus.isPaid()) {

            this.status = ReverseOrderStatus.CANCELED;
            this.payStatus = PayStatus.REFUNDED;
            this.refundCode = refundCode;

        } else {
            throw new BusinessException("只能在待退款并且支付才可以标记退款");
        }

        return this;
    }

    /**
     * 修改订单信息
     *
     * @param agentCompany
     * @return
     */
    public ReverseOrder editOrderInfo(AgentCompany agentCompany) {

        this.primaryAgentCompany = agentCompany;

        return this;
    }


    /**
     * 重新设置价格
     *
     * @param resetPrice
     * @param costPrice
     * @param lastPayTime
     * @return
     */
    public ReverseOrder resetPrice(BigDecimal resetPrice, BigDecimal costPrice, Date lastPayTime) {

        if (resetPrice == null || resetPrice.compareTo(this.price) < 0) {
            throw new BusinessException("价格小于当前价格");
        }
        this.price = resetPrice;
        this.costPrice =costPrice;
        this.lastPayTime = lastPayTime;

        this.status = ReverseOrderStatus.UNPAID;
        this.payStatus = PayStatus.UNPAID;
        if (this.price != null && resetPrice.compareTo(this.price) > 0){
            this.payStatus = PayStatus.PART_PAY;
        }
        return this;
    }

    /**
     * 获取需要支付的价格
     *
     * @return
     */
    @Transient
    public BigDecimal getNeedPayPrice() {

        if (this.actualPayPrice == null){
            return this.getPrice();
        }
        BigDecimal subtract = this.getPrice().subtract(this.actualPayPrice);

        return subtract;
    }

    @Transient
    public BigDecimal getPrettyNeedPayPrice(){

        BigDecimal divide = getNeedPayPrice().divide(new BigDecimal(100));

        return divide;
    }

    /**
     * 是否需要支付
     * @return
     */
    @Transient
    public boolean isNeedPay(){

        if (status.isConsumed()
                || status.isCanceled()
                || status.isWaitingForRefund()
                || status.isTicketed()
                || status.isWaitingForTicket()){

            return false;
        }
        if (this.getNeedPayPrice() == null || this.getNeedPayPrice().compareTo(BigDecimal.ZERO) > 0){
            return true;
        }
        return false;
    }

    /**
     * 是否是部分支付
     * @return
     */
    @Transient
    public boolean isPartialPay(){
        if (actualPayPrice != null && actualPayPrice.compareTo(BigDecimal.ZERO) > 0 && isNeedPay()){
            return true;
        }
        return false;
    }

    /**
     * 有实际付款吗
     * @return
     */
    @Transient
    public boolean hasActualPayPrice(){
        if (actualPayPrice != null && actualPayPrice.compareTo(BigDecimal.ZERO) > 0){
            return true;
        }
        return false;
    }

    /**
     * 修改邮件
     * @param email
     * @return
     */
    public ReverseOrder editEmail(String email) {

        this.customEmail = email;

        return this;
    }

    /**
     * 是否可以取消
     * @return
     */
    @Transient
    public boolean isCouldCancel(){

        if (status.isUnpaid()){
            return true;
        }
        return false;
    }

    /**
     *
     */
    public void initCruisesRequest() {

        this.cruisesRequest = new CruisesRequest();
    }

    /**
     *  修改英文姓和英文名
     * @param customName
     * @param customPrefix
     * @return
     */
    public ReverseOrder editCustomNameAndPrefix(String customName, String customPrefix) {
        this.customEnglishName = customName;
        this.customEnglishPrefix = customPrefix;
        return this;
    }

    /**
     *
     * @param title
     * @return
     * @deprecated use bingSku(Sku)
     *
     */
    @Deprecated
    public ReverseOrder editTitle(String title) {
        this.title = title;
        return this;
    }

    /**
     * 绑定sku
     * @param sku
     * @return
     */
    public ReverseOrder bingSku(Sku sku) {

        this.sku = sku;
        this.title = sku.getTitle();
        this.skuPic = sku.getPic();

        return this;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Agent getAgent() {
        return agent;
    }

    public void setAgent(Agent agent) {
        this.agent = agent;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public HotelRequest getHotelRequest() {
        return hotelRequest;
    }

    public void setHotelRequest(HotelRequest hotelRequest) {
        this.hotelRequest = hotelRequest;
    }

    public HotelBook getHotelBook() {
        return hotelBook;
    }

    public void setHotelBook(HotelBook hotelBook) {
        this.hotelBook = hotelBook;
    }

    public CruisesRequest getCruisesRequest() {
        return cruisesRequest;
    }

    public void setCruisesRequest(CruisesRequest cruisesRequest) {
        this.cruisesRequest = cruisesRequest;
    }

    public CruisesBook getCruisesBook() {
        return cruisesBook;
    }

    public void setCruisesBook(CruisesBook cruisesBook) {
        this.cruisesBook = cruisesBook;
    }

    public JourneyRequest getJourneyRequest() {
        return journeyRequest;
    }

    public void setJourneyRequest(JourneyRequest journeyRequest) {
        this.journeyRequest = journeyRequest;
    }

    public JourneyBook getJourneyBook() {
        return journeyBook;
    }

    public void setJourneyBook(JourneyBook journeyBook) {
        this.journeyBook = journeyBook;
    }

    public boolean isDisabled() {
        return disabled;
    }

    public void setDisabled(boolean disabled) {
        this.disabled = disabled;
    }


    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public ReverseOrderStatus getStatus() {
        return status;
    }

    public void setStatus(ReverseOrderStatus status) {
        this.status = status;
    }

    public ReverseOrderType getType() {
        return type;
    }

    public void setType(ReverseOrderType type) {
        this.type = type;
    }

    public AviationBook getAviationBook() {
        return aviationBook;
    }

    public void setAviationBook(AviationBook aviationBook) {
        this.aviationBook = aviationBook;
    }

    public AviationRequest getAviationRequest() {
        return aviationRequest;
    }

    public void setAviationRequest(AviationRequest aviationRequest) {
        this.aviationRequest = aviationRequest;
    }

    public BigDecimal getCostPrice() {
        return costPrice;
    }

    public void setCostPrice(BigDecimal costPrice) {
        this.costPrice = costPrice;
    }


    public Enquiry getEnquiry() {
        return enquiry;
    }

    public void setEnquiry(Enquiry enquiry) {
        this.enquiry = enquiry;
    }

    public Principal getOperator() {
        return operator;
    }

    public void setOperator(Principal operator) {
        this.operator = operator;
    }


    public PayStatus getPayStatus() {
        return payStatus;
    }

    public void setPayStatus(PayStatus payStatus) {
        this.payStatus = payStatus;
    }


    public BigDecimal getActualPayPrice() {
        return actualPayPrice;
    }

    public void setActualPayPrice(BigDecimal actualPayPrice) {
        this.actualPayPrice = actualPayPrice;
    }

    public Date getPayTime() {
        return payTime;
    }

    public void setPayTime(Date payTime) {
        this.payTime = payTime;
    }


    public String getPayCode() {
        return payCode;
    }

    public void setPayCode(String payCode) {
        this.payCode = payCode;
    }

    public String getOrderRemark() {
        return orderRemark;
    }

    public void setOrderRemark(String orderRemark) {
        this.orderRemark = orderRemark;
    }

    public Principal getMarkPayOperator() {
        return markPayOperator;
    }

    public void setMarkPayOperator(Principal markPayOperator) {
        this.markPayOperator = markPayOperator;
    }

    public OrderPayType getPayType() {
        return payType;
    }

    public void setPayType(OrderPayType payType) {
        this.payType = payType;
    }

    public String getTicketOrderCode() {
        return ticketOrderCode;
    }

    public void setTicketOrderCode(String ticketOrderCode) {
        this.ticketOrderCode = ticketOrderCode;
    }

    public Date getTicketTime() {
        return ticketTime;
    }

    public void setTicketTime(Date ticketTime) {
        this.ticketTime = ticketTime;
    }

    public BigDecimal getRefundPrice() {
        return refundPrice;
    }

    public void setRefundPrice(BigDecimal refundPrice) {
        this.refundPrice = refundPrice;
    }

    public Date getConsumedTime() {
        return consumedTime;
    }

    public void setConsumedTime(Date consumedTime) {
        this.consumedTime = consumedTime;
    }

    public String getRefundCode() {
        return refundCode;
    }

    public void setRefundCode(String refundCode) {
        this.refundCode = refundCode;
    }


    public String getCustomName() {
        return customName;
    }

    public void setCustomName(String customName) {
        this.customName = customName;
    }

    public String getCustomMobile() {
        return customMobile;
    }

    public void setCustomMobile(String customMobile) {
        this.customMobile = customMobile;
    }

    public String getCustomEmail() {
        return customEmail;
    }

    public void setCustomEmail(String customEmail) {
        this.customEmail = customEmail;
    }


    public AgentCompany getPrimaryAgentCompany() {
        return primaryAgentCompany;
    }

    public void setPrimaryAgentCompany(AgentCompany primaryAgentCompany) {
        this.primaryAgentCompany = primaryAgentCompany;
    }

    public Date getLastPayTime() {
        return lastPayTime;
    }

    public void setLastPayTime(Date lastPayTime) {
        this.lastPayTime = lastPayTime;
    }


    public String getPayPic() {
        return payPic;
    }

    public void setPayPic(String payPic) {
        this.payPic = payPic;
    }

    public Date getCancelTime() {
        return cancelTime;
    }

    public void setCancelTime(Date cancelTime) {
        this.cancelTime = cancelTime;
    }


    public boolean isMarkPay() {
        return markPay;
    }

    public void setMarkPay(boolean markPay) {
        this.markPay = markPay;
    }


    public boolean isOnlinePay() {
        return onlinePay;
    }

    public void setOnlinePay(boolean onlinePay) {
        this.onlinePay = onlinePay;
    }


    public String getCustomEnglishPrefix() {
        return customEnglishPrefix;
    }

    public void setCustomEnglishPrefix(String customEnglishPrefix) {
        this.customEnglishPrefix = customEnglishPrefix;
    }

    public String getCustomEnglishName() {
        return customEnglishName;
    }

    public void setCustomEnglishName(String customEnglishName) {
        this.customEnglishName = customEnglishName;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSkuPic() {
        return skuPic;
    }

    public void setSkuPic(String skuPic) {
        this.skuPic = skuPic;
    }

    public Sku getSku() {
        return sku;
    }

    public void setSku(Sku sku) {
        this.sku = sku;
    }
}
